﻿#include "mvbprotocalcache.h"
#include<QDebug>
#include <iostream>
#include <string>
#include <iomanip>
#include <sstream>
MVBProtocalCache::MVBProtocalCache()
{

}

void MVBProtocalCache::TransCacheToDataPars()
{
    for (auto iter = m_portDataPars.begin(); iter != m_portDataPars.end(); ++iter)
    {
        QString portAddress=iter.key();
        //不包含
        if(!m_portCache.contains(portAddress))
            continue;

        //端口类型
        iter->m_portType=m_portCache[portAddress].m_portType;

        //转换
        for(int varID=0;varID<iter.value().m_portVars.count();++varID)
        {
            deviceDataToPortVars(m_portCache[portAddress],iter.value(),varID);
        }
    }
}

/********************
BOOLEAN1
INTEGER8
INTEGER16
INTEGER32
UNSIGNED8
UNSIGNED16
UNSIGNED32
REAL32
ARRAYOFCHAR

input:
output:
return:
********************/
void MVBProtocalCache::TransCacheToDataPars(const QString &portAddress)
{

    //不包含
    if(!m_portCache.contains(portAddress))
    {
        qDebug()<<"缓存中未找到地址"+portAddress<<endl;
        return;
    }

    auto& Vars=m_portDataPars[portAddress].m_portVars;
    //转换
    for(int varID=0;varID<Vars.count();++varID)
    {
        deviceDataToPortVars(m_portCache[portAddress],m_portDataPars[portAddress],varID);
    }


}

void MVBProtocalCache::deviceDataToPortVars(const mvbDeviceData &deviceData, MVBPortData &portVars, int Varid)
{
    //引用变量 方便后续修改值
    auto& var = portVars.m_portVars[Varid];
    if(var.m_MVBtype=="BOOLEAN1")
    {
        //计算数据所在内存块位置
        int blockid = static_cast<int>(var.m_byteIndex/2);
        unsigned short tempShort=deviceData.shortData[blockid];
        if(portVars.m_portVars[Varid].m_byteIndex%2==1)
        {
            unsigned short temp=tempShort>>var.m_bitIndex;
            if((temp&0x0001))
            {
                var.m_cellValue=true;
            }
            else
            {
                var.m_cellValue=false;
            }

        }
        else
        {
            unsigned short temp=tempShort>>(var.m_bitIndex+8);
            if((temp&0x0001))
            {
                var.m_cellValue=true;
            }
            else
            {
                var.m_cellValue=false;
            }

        }

    }
    else if(portVars.m_portVars[Varid].m_MVBtype=="UNSIGNED8")
    {
        //计算数据所在内存块位置
        int blockid = static_cast<int>(var.m_byteIndex/2);
        unsigned short tempShort=deviceData.shortData[blockid];
        if(portVars.m_portVars[Varid].m_byteIndex%2==1)
        {
            //保留低位（要读取的位置）
            tempShort=tempShort&0x00FF;
            var.m_cellValue = tempShort;

        }
        else
        {
            //获取高8位
            tempShort=tempShort>>8;
            var.m_cellValue =tempShort;
        }

    }
    else if(portVars.m_portVars[Varid].m_MVBtype=="UNSIGNED16")
    {
        int blockid = static_cast<int>(var.m_byteIndex/2);
        var.m_cellValue= deviceData.shortData[blockid];

    }
    else if(portVars.m_portVars[Varid].m_MVBtype=="UNSIGNED32")
    {
        int blockid = static_cast<int>(portVars.m_portVars[Varid].m_byteIndex/2);
        unsigned int temp= var.m_cellValue.toUInt();
        unsigned int uint32[2]{0};

        unsigned int low16Bit = deviceData.shortData[blockid+1];  //低16位
        low16Bit=low16Bit&0x0000FFFF;
        unsigned int high16Bit = deviceData.shortData[blockid];  //高16位
        high16Bit=high16Bit<<16;
        var.m_cellValue = high16Bit|low16Bit;

    }
    else if(portVars.m_portVars[Varid].m_MVBtype=="INTEGER8")
    {
        //计算数据所在内存块位置
        int blockid = static_cast<int>(var.m_byteIndex/2);
        unsigned short tempShort=deviceData.shortData[blockid];
        if(portVars.m_portVars[Varid].m_byteIndex%2==1)
        {
            //保留低位（要读取的位置）
            tempShort=tempShort&0x00FF;
            var.m_cellValue = tempShort;

        }
        else
        {
            //获取高8位
            tempShort=tempShort>>8;
            var.m_cellValue =tempShort;
        }
    }
    else if(portVars.m_portVars[Varid].m_MVBtype=="INTEGER16")
    {
        int blockid = static_cast<int>(var.m_byteIndex/2);
        var.m_cellValue= deviceData.shortData[blockid];
    }
    else if(portVars.m_portVars[Varid].m_MVBtype=="INTEGER32")
    {
        int blockid = static_cast<int>(portVars.m_portVars[Varid].m_byteIndex/2);
        unsigned int temp= var.m_cellValue.toUInt();
        unsigned int uint32[2]{0};

        unsigned int low16Bit = deviceData.shortData[blockid+1];  //低16位
        low16Bit=low16Bit&0x0000FFFF;
        unsigned int high16Bit = deviceData.shortData[blockid];  //高16位
        high16Bit=high16Bit<<16;
        var.m_cellValue = high16Bit|low16Bit;

    }
    else if(portVars.m_portVars[Varid].m_MVBtype=="REAL32")
    {
        //暂时没有Real类型的数据
        //        float floatValue= portVars.m_portVars[Varid].m_cellValue.toFloat();
        //        int blockid = static_cast<int>(portVars.m_portVars[Varid].m_byteIndex/2);

        //        unsigned char buffer[4]; // 创建一个字符数组来存储 float 的位表示

        //        // 将 float 值复制到字符数组中
        //        memcpy(buffer, &floatValue, sizeof(floatValue));

        //        // 将字符数组的前两个字节转换为 ushort
        //        ushort low = (buffer[1] << 8) | buffer[0];
        //        // 将字符数组的后两个字节转换为 ushort
        //        ushort high = (buffer[3] << 8) | buffer[2];

        //        deviceData.shortData[blockid] = low;
        //        deviceData.shortData[blockid+1] =high;

    }
    else
    {

    }
}


void MVBProtocalCache::portVarsToDeviceData(const MVBPortData &portVars, mvbDeviceData &deviceData, int Varid)
{
    const auto var = portVars.m_portVars[Varid];
    if(portVars.m_portVars[Varid].m_MVBtype=="BOOLEAN1")
    {
        //计算数据所在内存块位置
        int blockid = static_cast<int>(portVars.m_portVars[Varid].m_byteIndex/2);
        unsigned short tempShort=deviceData.shortData[blockid];
        if(portVars.m_portVars[Varid].m_byteIndex%2==1)
        {
            unsigned short temp=tempShort>>portVars.m_portVars[Varid].m_bitIndex;
            if((temp&0x0001)!=var.m_cellValue.toBool())
            {
                tempShort=invertBit(tempShort,portVars.m_portVars[Varid].m_bitIndex);
            }
        }
        else
        {
            unsigned short temp=tempShort>>(portVars.m_portVars[Varid].m_bitIndex+8);
            if((temp&0x0001)!=var.m_cellValue.toBool())
            {
                tempShort=invertBit(tempShort,portVars.m_portVars[Varid].m_bitIndex+8);
            }
        }
        deviceData.shortData[blockid]=tempShort;

    }
    else if(portVars.m_portVars[Varid].m_MVBtype=="UNSIGNED8")
    {
        //计算数据所在内存块位置
        int blockid = static_cast<int>(portVars.m_portVars[Varid].m_byteIndex/2);
        unsigned short tempShort=deviceData.shortData[blockid];
        unsigned short modifyUnsigned8=0x0000;
        if(portVars.m_portVars[Varid].m_byteIndex%2==1)
        {
            modifyUnsigned8=portVars.m_portVars[Varid].m_cellValue.toUInt();
            //重置低位（要修改的地方） 保留高位
            tempShort&=0xFF00;
            tempShort|=modifyUnsigned8;

        }
        else
        {
            modifyUnsigned8=portVars.m_portVars[Varid].m_cellValue.toUInt()<<8;
            //重置高位 保留低位
            tempShort&=0x00FF;
            //修改高位
            tempShort|=modifyUnsigned8;
        }
        deviceData.shortData[blockid]=tempShort;
    }
    else if(portVars.m_portVars[Varid].m_MVBtype=="UNSIGNED16")
    {
        unsigned short modifyShort= portVars.m_portVars[Varid].m_cellValue.toUInt();
        int blockid = static_cast<int>(portVars.m_portVars[Varid].m_byteIndex/2);
        deviceData.shortData[blockid]=modifyShort;

    }
    else if(portVars.m_portVars[Varid].m_MVBtype=="UNSIGNED32")
    {
        int blockid = static_cast<int>(portVars.m_portVars[Varid].m_byteIndex/2);
        unsigned int temp= portVars.m_portVars[Varid].m_cellValue.toUInt();
        unsigned short uint16[2]{0};

        uint16[1] = (temp) & 0xFFFF;  //低16位
        uint16[0] = (temp >>16 ) & 0xFFFF;  //高16位
        deviceData.shortData[blockid] = uint16[0];
        deviceData.shortData[blockid+1] = uint16[1];

    }
    else if(portVars.m_portVars[Varid].m_MVBtype=="INTEGER8")
    {
        //计算数据所在内存块位置
        int blockid = static_cast<int>(portVars.m_portVars[Varid].m_byteIndex/2);
        unsigned short tempShort=deviceData.shortData[blockid];
        unsigned short modifyUnsigned8=0x0000;
        if(portVars.m_portVars[Varid].m_byteIndex%2==1)
        {
            modifyUnsigned8=portVars.m_portVars[Varid].m_cellValue.toUInt();
            //重置低位（要修改的地方） 保留高位
            tempShort&=0xFF00;
            tempShort|=modifyUnsigned8;

        }
        else
        {
            modifyUnsigned8=portVars.m_portVars[Varid].m_cellValue.toUInt()<<8;
            //重置高位 保留低位
            tempShort&=0x00FF;
            //修改高位
            tempShort|=modifyUnsigned8;
        }
        deviceData.shortData[blockid]=tempShort;
    }
    else if(portVars.m_portVars[Varid].m_MVBtype=="INTEGER16")
    {
        unsigned short modifyShort= portVars.m_portVars[Varid].m_cellValue.toUInt();
        int blockid = static_cast<int>(portVars.m_portVars[Varid].m_byteIndex/2);
        deviceData.shortData[blockid]=modifyShort;
    }
    else if(portVars.m_portVars[Varid].m_MVBtype=="INTEGER32")
    {
        int blockid = static_cast<int>(portVars.m_portVars[Varid].m_byteIndex/2);
        unsigned int temp= portVars.m_portVars[Varid].m_cellValue.toUInt();


        ushort low = (temp) & 0xFFFF;  //低16位
        ushort high= (temp >>16 ) & 0xFFFF;  //高16位
        deviceData.shortData[blockid] = low;
        deviceData.shortData[blockid+1] =high;

    }
    else if(portVars.m_portVars[Varid].m_MVBtype=="REAL32")
    {
        //暂时没有Real类型的数据
        //        float floatValue= portVars.m_portVars[Varid].m_cellValue.toFloat();
        //        int blockid = static_cast<int>(portVars.m_portVars[Varid].m_byteIndex/2);

        //        unsigned char buffer[4]; // 创建一个字符数组来存储 float 的位表示

        //        // 将 float 值复制到字符数组中
        //        memcpy(buffer, &floatValue, sizeof(floatValue));

        //        // 将字符数组的前两个字节转换为 ushort
        //        ushort low = (buffer[1] << 8) | buffer[0];
        //        // 将字符数组的后两个字节转换为 ushort
        //        ushort high = (buffer[3] << 8) | buffer[2];

        //        deviceData.shortData[blockid] = low;
        //        deviceData.shortData[blockid+1] =high;

    }
    else
    {

    }
}

void MVBProtocalCache::WritePortData(const QString &portAddress, const QString &varName, const QVariant &value,int varID)
{
    if(!m_portDataPars.contains(portAddress))
        return;
    auto &portvalue = m_portDataPars[portAddress];
    //    if(portvalue.m_portType!=1) //源端口才能写入数据
    //    {
    //        return;
    //    }

    //转换变量为内存数据
    portVarsToDeviceData(portvalue,m_portCache[portAddress],varID);
    printHexData(m_portCache[portAddress].shortData,m_portCache[portAddress].m_size/2);

}

void MVBProtocalCache::resetAllDeviceData()
{
    for (auto iter = m_portCache.begin(); iter != m_portCache.end(); ++iter)
    {
        memset(iter.value().shortData,0,iter.value().m_size);
    }
    TransCacheToDataPars();
}


void MVBProtocalCache::printHexData(unsigned short* data,unsigned int size)
{
    for (size_t i = 0; i <size; ++i)
    {
        // 使用std::setw(2)和std::setfill('0')确保十六进制数是两位
        std::cout << std::hex << std::setw(4) << std::setfill('0') << static_cast<int>(data[i]);
        std::cout << " "; // 在每个字节后打印空格
    }
    std::cout<<std::endl;
}
//取反指定位
short MVBProtocalCache::invertBit(short value, int bitIndex) {
    // 检查字节索引是否有效
    if (bitIndex < 0 || bitIndex > 16) {
        qDebug() << "Invalid byte index. Must be 0 -16." << endl;
        return value;
    }

    // 创建一个掩码，用于取反指定的字节
    unsigned short mask = 0x01; // 0xFF是8位全1的掩码

    // 根据字节索引，决定掩码应该左移多少位
    mask <<= bitIndex;

    // 使用掩码对指定的字节进行取反
    value ^= mask;

    return value;
}
